#include "button.h"

#include "tool_common.h"

static const char *TAG_BUTTON = "ESP BUTTON";

/* 引脚定义 */
#define BOOT_INT_GPIO_PIN   GPIO_NUM_0

#define SHORT_PRESS_TIME_MS 500    // 短按时间阈值
#define MEDIUM_PRESS_TIME_MS 3000  // 中按时间阈值
#define LONG_PRESS_TIME_MS 5000    // 长按时间阈值

static TimerHandle_t button_timer;
static bool button_pressed = false;
static int64_t press_start_time = 0;
static uint8_t button_pressed_val = 0;
static uint32_t button_statue_val = 0;

static void IRAM_ATTR exit_gpio_isr_handler(void *arg) {
    // 中断中不能打印
    uint32_t gpio_num = (uint32_t) arg;
    int64_t now = esp_timer_get_time();
    if (gpio_get_level(BOOT_INT_GPIO_PIN) == 0) {
        // 按键按下
        press_start_time = now;
        button_pressed = true;
        if (xTimerStartFromISR(button_timer, NULL) != pdPASS) {
            button_pressed_val = -1;
        }
    } else {
        if (button_pressed) {
            // 按键松开,定时器未超时
            int64_t press_duration = now - press_start_time;
            if (xTimerStopFromISR(button_timer, NULL) != pdPASS) {
                button_pressed_val = -1;
            }
            if (press_duration < SHORT_PRESS_TIME_MS * 1000) {
                button_pressed_val = 1;
                button_statue_val = 1;
            } else if (press_duration >= SHORT_PRESS_TIME_MS * 1000 && press_duration < MEDIUM_PRESS_TIME_MS * 1000) {
                button_pressed_val = 2;
                button_statue_val = 2;
            }
            button_pressed = false;
        } else {
            button_pressed_val = 3;
            if (xTimerStopFromISR(button_timer, NULL) != pdPASS) {
                button_pressed_val = -1;
            }
        }

    }
}

void button_restart(void *args)
{
    while (1) {
        switch(button_pressed_val) {
            case 1:
                ESP_LOGI(TAG_BUTTON, "短按");
                button_pressed_val = 0;
                break;
            case 2:
                ESP_LOGI(TAG_BUTTON, "中按");
                button_pressed_val = 0;
                break;
            case 3:
                ESP_LOGI(TAG_BUTTON, "长按");
                // 重置系统为AP_DNS
                set_config_module(AP_DNS);
                esp_restart();
                button_pressed_val = 0;
                break;
            default:
                if (button_pressed_val == -1) {
                    ESP_LOGI(TAG_BUTTON, "BUTTON Timer error");
                    button_pressed_val = 0;
                }
                vTaskDelay(pdMS_TO_TICKS(200));
                break;
        }
    }
}

static void button_timer_callback(TimerHandle_t xTimer) {
    // 定期器超时,确定是否长按
    if (button_pressed) {
        button_pressed = false;
    }
}

void btn_input_level_init(void)
{
    /* 配置BOOT引脚和外部中断 */
    gpio_config_t gpio_init_struct = {
        .mode = GPIO_MODE_INPUT,                     /* 选择为输入模式 */
        .pull_up_en = GPIO_PULLUP_ENABLE,            /* 上拉使能 */
        .pull_down_en = GPIO_PULLDOWN_DISABLE,       /* 下拉失能 */
        .intr_type = GPIO_INTR_DISABLE,              /* 双边沿触发 */
        .pin_bit_mask = 1ull << BOOT_INT_GPIO_PIN,   /* 配置BOOT按键引脚 */
    };
    ESP_ERROR_CHECK(gpio_config(&gpio_init_struct)); /* 配置使能 */
}

void button_init(void)
{
    /* 配置BOOT引脚和外部中断 */
    gpio_config_t gpio_init_struct = {
        .mode = GPIO_MODE_INPUT,                     /* 选择为输入模式 */
        .pull_up_en = GPIO_PULLUP_ENABLE,            /* 上拉使能 */
        .pull_down_en = GPIO_PULLDOWN_DISABLE,       /* 下拉失能 */
        .intr_type = GPIO_INTR_ANYEDGE,              /* 双边沿触发 */
        .pin_bit_mask = 1ull << BOOT_INT_GPIO_PIN,   /* 配置BOOT按键引脚 */
    };
    ESP_ERROR_CHECK(gpio_config(&gpio_init_struct)); /* 配置使能 */

    /* 注册中断服务 */
    ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_EDGE));
    
    /* 设置GPIO的中断回调函数 */
    ESP_ERROR_CHECK(gpio_isr_handler_add(BOOT_INT_GPIO_PIN, exit_gpio_isr_handler, (void*) BOOT_INT_GPIO_PIN));

    /* 使能 GPIO 模块中断信号 */
    gpio_intr_enable(BOOT_INT_GPIO_PIN);

    // 创建定时器
    button_timer = xTimerCreate("button_timer", pdMS_TO_TICKS(MEDIUM_PRESS_TIME_MS), pdFALSE, NULL, button_timer_callback);
    
    // 创建按键检测定时器,重启设备
    xTaskCreate(button_restart, "button_timer_task", 2048, NULL, 1, NULL);
}

int scanf_key(void)
{
    return gpio_get_level(BOOT_INT_GPIO_PIN);
}

uint32_t get_button_val(void)
{
    uint32_t val = button_statue_val;
    button_statue_val = 0;
    return val;
}